package com.andnnl.utils;

import info.monitorenter.cpdetector.io.*;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * Created by chenss on 2021/6/3.
 */
public class FileCharsetUtil {
    private static class Holder {
        /*
         * detector是探测器，它把探测任务交给具体的探测实现类的实例完成。
         * cpDetector内置了一些常用的探测实现类，这些探测实现类的实例可以通过add方法 加进来，如ParsingDetector、
         * JChardetFacade、ASCIIDetector、UnicodeDetector。
         * detector按照“谁最先返回非空的探测结果，就以该结果为准”的原则返回探测到的
         * 字符集编码。使用需要用到三个第三方JAR包：antlr.jar、chardet.jar和cpdetector.jar
         * cpDetector是基于统计学原理的，不保证完全正确。
         */
        static CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
        {
            /*
             * ParsingDetector可用于检查HTML、XML等文件或字符流的编码,构造方法中的参数用于
             * 指示是否显示探测过程的详细信息，为false不显示。
             */
            detector.add(new ParsingDetector(false));
            /*
             * JChardetFacade封装了由Mozilla组织提供的JChardet，它可以完成大多数文件的编码
             * 测定。所以，一般有了这个探测器就可满足大多数项目的要求，如果你还不放心，可以
             * 再多加几个探测器，比如下面的ASCIIDetector、UnicodeDetector等。
             */
            detector.add(JChardetFacade.getInstance());// 用到antlr.jar、chardet.jar
            // ASCIIDetector用于ASCII编码测定
            detector.add(ASCIIDetector.getInstance());
            // UnicodeDetector用于Unicode家族编码的测定
            detector.add(UnicodeDetector.getInstance());
        }
    }

    /**
     * 方法一： 仅作参考，不准确
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static String getCharset(File file) {
        String code = "GBK";
        BufferedInputStream bin = null;
        try {
            bin = new BufferedInputStream(new FileInputStream(
                    file));
            int p = (bin.read() << 8) + bin.read();
            switch (p) {
                case 0xEFBB:
                    code = "UTF-8";
                    break;
                case 0xFFFE:
                    code = "Unicode";
                    break;
                case 0xFEFF:
                    code = "UTF-16BE";
                    break;
                default:
                    code = "GBK";
            }
            return code;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return code;

    }

    /**
     * 方法二： 仅作参考，不准确
     *
     * @param head
     * @return
     */
    public static String getCharset(byte[] head) {
        byte[] codehead = new byte[4];
        // 截取数组
        System.arraycopy(head, 0, codehead, 0, 4);
        String code = "GBK";
        if (head[0] == -1 && head[1] == -2) {
            code = "UTF-16";
        } else if (head[0] == -2 && head[1] == -1) {
            code = "Unicode";
        } else if (head[0] == -17 && head[1] == -69 && head[2] == -65)
            code = "UTF-8";
        else {
            code = "GBK";
        }
        return code;
    }

    /**
     * 利用第三方开源包cpdetector获取文件编码格式，文件太大时会卡死
     */
    public static String getFileEncode(File file) {
        java.nio.charset.Charset charset = null;
//        File f = new File(path);
        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
//            charset = detector.detectCodepage(f.toURI().toURL());
            charset = Holder.detector.detectCodepage(in, 1024);
//            charset = codeTest(in,2147483647);
//            System.out.println(charset);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        if (charset != null)
            return charset.name();
        else
            return "GBK";
    }


}
